package com.lf.freezingpoint.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lf.freezingpoint.common.entity.Claims;
import com.lf.freezingpoint.common.entity.R;
import com.lf.freezingpoint.common.util.JWTUtil;
import com.lf.freezingpoint.entity.SysUser;
import com.lf.freezingpoint.service.LoginService;
import com.lf.freezingpoint.service.SysUserService;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

@Service
public class LoginServiceImpl implements LoginService {
    private static final Logger logger = Logger.getLogger(LoginServiceImpl.class.toString());

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AuthenticationManagerBuilder authenticationManagerBuilder;

    @Override
    public R login(SysUser sysUser) {
        //获取用户名密码
        String username = sysUser.getUsername();
        String password = sysUser.getPassword();

        //用户认证
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(usernamePasswordAuthenticationToken);
        if (ObjectUtils.isEmpty(authentication)) {
            return R.fail("用户名或密码错误");
        }
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();

        //生成jwt并返回
        SysUser sysUser1 = sysUserService.getSysUserInfoByUsername(username);
        List<String> roles = new ArrayList<>();
        sysUser1.getRoles().forEach(role -> roles.add(role.getRoleKey()));

        Claims claims = Claims.builder()
                .userId(sysUser1.getUserId())
                .username(sysUser1.getUsername())
                .roles(roles)
                .build();

        String token = new JWTUtil().createToken(claims);

        JSONObject data = new JSONObject();
        data.put("user", sysUser1);
        data.put("token", token);

        redisTemplate.opsForValue().set(username, JSON.toJSONString(userDetails), 7, TimeUnit.DAYS);

        return R.ok(data, "登录成功");
    }

    @Override
    public R logout(HttpServletRequest request) {
        String authorization = request.getHeader("Authorization");
        logger.info("携带authorization:" + authorization);

        if (StringUtils.isBlank(authorization)) {
            return R.fail("token无效,登出失败");
        }
        String realToken = authorization.replace("Bearer ", "");

        //是：校验jwt有效性
        R r = JWTUtil.verifyToken(realToken);
        if (R.isError(r)) {
            return R.fail(r.getMsg());
        }

        if (redisTemplate.hasKey(realToken)) {
            return R.fail("token无效");
        }

        Claims claims = (Claims) r.getData();
        String username = claims.getUsername();
        redisTemplate.delete(username);
        redisTemplate.opsForValue().set(realToken, username, 7, TimeUnit.DAYS);

        return R.ok("登出成功");
    }
}
